package com.forestar.xzk.commongisutil.CoordinateRelationship;

import android.util.SparseArray;
/**
 * @author Administrator by xzk
 * @data 2020/7/23  16:18
 * @email CoordinateSystem
 * @remark   世界坐标与屏幕坐标的对应关系
 *
 */
public class CoordinateSystem
  {
    public static final float DEG2RAD = (float) (Math.PI / 180.0);
    public static final float RAD2DEG = (float) (180.0 / Math.PI);
    public static final int RADIUS_EARTH_METERS = 6378137;

    private static final int SRID_BJ54 = 4214;
    private static final int SRID_XIAN80 = 4610;
    private static final int SRID_WGS84 = 4326;
    private static final int SRID_MERCATOR = 900913;
    private static final int SRID_CGCS2000 = 4490;
    private static boolean isAllGeoCoordTransParamsEnabled = true;
    private String name;
    private int srid;
    private static SparseArray<CoordinateSystem> coordSystemMap = new SparseArray<>();
    private static CoordinateSystem WGS84LngLat = CoordinateSystem.createWGS84();

    private CoordinateSystem(int srid)
      {
        this.srid = srid;
        // TODO 这里需要分析坐标单位，度，米，还有墨卡托的不能用于测量的单位
      }

    private static String getTransformerKey(CoordinateSystem from, CoordinateSystem to)
      {
        return String.valueOf(from.getSrid()) + "->" + String.valueOf(to.getSrid());
      }

    // 可强制设定所有的坐标转换是否使用设置的GNSS转换参数，用于简单偏移校正场景，不使用五参数、七参数、四参数等
    public static void setAllGeoCoordTransParamsEnable(boolean enabled)
      {
        isAllGeoCoordTransParamsEnabled = enabled;
      }

    public static double pointDistanceToPoint(double lon1, double lat1, double lon2, double lat2)
      {
        final double a1 = DEG2RAD * lat1;
        final double a2 = DEG2RAD * lon1;
        final double b1 = DEG2RAD * lat2;
        final double b2 = DEG2RAD * lon2;
        final double cosa1 = Math.cos(a1);
        final double cosb1 = Math.cos(b1);
        final double t1 = cosa1 * Math.cos(a2) * cosb1 * Math.cos(b2);
        final double t2 = cosa1 * Math.sin(a2) * cosb1 * Math.sin(b2);
        final double t3 = Math.sin(a1) * Math.sin(b1);
        final double tt = Math.acos(t1 + t2 + t3);
        return (int) (RADIUS_EARTH_METERS * tt);
      }

    public static CoordinateSystem createMercator()
      {
        return create(SRID_MERCATOR);
      }

    /**
     * 是否是地理坐标系统
     *
     * @return
     */
    public boolean isGeographicCoordinateSystem()
      {
        return srid == SRID_BJ54 || srid == SRID_WGS84 || srid == SRID_XIAN80 || srid == SRID_CGCS2000;
      }

    /**
     * 是否是投影（平面）坐标系统
     *
     * @return
     */
    public boolean isProjectCoordinateSystem()
      {
        if (srid == 4326)
          {
            return false;
          } else if (srid == 4214)
          {
            //"北京1954坐标系 经纬度";
            return false;
          } else if (srid == 4610)
          {
            //""西安1980坐标系 经纬度";
            return false;
          } else if (srid == 4490)
          {
            //""国家2000坐标系 经纬度";
            return false;
          }
        return true;
      }

    /**
     * 根据SRID创建坐标系统对象，一次创建，重复使用
     *
     * @param srid
     * @return
     */
    public static CoordinateSystem create(int srid)
      {
        CoordinateSystem coordinateSystem = coordSystemMap.get(srid);
        if (coordinateSystem != null)
          {
            return coordinateSystem;
          }
        CoordinateSystem cs = new CoordinateSystem(srid);
        coordSystemMap.put(srid, cs);
        return cs;
      }

    public static CoordinateSystem createBeijing1954()
      {
        return new CoordinateSystem(4214);
      }

    public static CoordinateSystem createXian1980()
      {
        return new CoordinateSystem(4610);
      }

    public static CoordinateSystem createWGS84()
      {
        return new CoordinateSystem(4326);
      }

    public static CoordinateSystem createCGCS2000()
      {
        return new CoordinateSystem(4490);
      }

    public boolean equals(Object other)
      {
        if (this == other)
          return true;
        if (other == null)
          return false;
        if (!(other instanceof CoordinateSystem))
          return false;
        final CoordinateSystem cat = (CoordinateSystem) other;
        if (getSrid() != cat.getSrid())
          return false;
        return true;
      }

    public int getSrid()
      {
        return srid;
      }

    public static void lonLat2Mercator(double[][] lngLats)
      {
        for (int i = 0; i < lngLats.length; i++)
          {
            lngLats[i][0] = lngLats[i][0] * 20037508.3427892 / 180;
            lngLats[i][1] = Math.log(Math.tan((90 + lngLats[i][1]) * 3.14159265358979323846 / 360)) / (3.14159265358979323846 / 180);
            lngLats[i][1] *= 20037508.347892 / 180;
          }
      }

    public static void Mercator2lonLat(double[][] lngLats)
      {
        for (int i = 0; i < lngLats.length; i++)
          {
            lngLats[i][0] = lngLats[i][0] / 20037508.347892 * 180;
            lngLats[i][1] = lngLats[i][1] / 20037508.347892 * 180;
            lngLats[i][1] = 180 / 3.14159265358979323846 * (2 * Math.atan(Math.exp(lngLats[i][1] * 3.14159265358979323846 / 180)) - 3.14159265358979323846 / 2);
          }
      }

    public static void lonLat2Mercator(double lon, double lat, double[] outxy)
      {
        lon = lon * 20037508.347892 / 180;
        lat = Math.log(Math.tan((90 + lat) * 3.14159265358979323846 / 360)) / (3.14159265358979323846 / 180);
        lat *= 20037508.347892 / 180;
        outxy[0] = lon;
        outxy[1] = lat;
      }

    public static void Mercator2lonLat(double lon, double lat, double[] outxy)
      {
        lon = lon / 20037508.347892 * 180;
        lat = lat / 20037508.347892 * 180;
        lat = 180 / 3.14159265358979323846 * (2 * Math.atan(Math.exp(lat * 3.14159265358979323846 / 180)) - 3.14159265358979323846 / 2);
        outxy[0] = lon;
        outxy[1] = lat;
      }

    // 底层转换
    public static void projectPointsArray(double[] xy, int numPoints)
      {
      }

    public boolean equalsEllipsoid(CoordinateSystem to)
      {
        return false;
      }

    public boolean baseOnXian80()
      {
        return false;
      }

    public boolean baseOnBeijing54()
      {
        return false;
      }

    public boolean baseOnWGS84()
      {
        return srid == SRID_WGS84;
      }

    public boolean baseOnCGCS2000()
      {
        return srid == SRID_CGCS2000;
      }

    public boolean isWebMercator()
      {
        return srid == SRID_MERCATOR;
      }

    public CoordinateSystem getGeographicCoordinateSystem()
      {
        // TODO 这里必须要求算其真实地理坐标系统 这里只是为测试用 liubo 2016年8月8日15:11:21
        CoordinateSystem geographicCoordinateSystem = null;
        if (this.srid == SRID_MERCATOR)
          {
            return CoordinateSystem.createWGS84();
          }
        String strCoorDes = "";
        if (srid == 3395 || srid == 900913 || srid == 3857 || srid == 102100 || srid == 102113 || srid == 54004)
          {
            strCoorDes = "世界墨卡托投影坐标系";
            return CoordinateSystem.createWGS84();
          } else if (srid == 4326)
          {
            strCoorDes = "WGS84坐标系 经纬度";
            return this;
          } else if (srid == 4214)
          {
            strCoorDes = "北京1954坐标系 经纬度";
            return this;
          } else if (srid == 4610)
          {
            strCoorDes = "西安1980坐标系 经纬度";
            return this;
          } else if (srid == 4490)
          {
            strCoorDes = "国家2000坐标系 经纬度";
            return this;
          } else if (srid > 2400 && srid < 2422)
          {
            strCoorDes = "北京54坐标系3度分带" + String.valueOf(srid - 2400 + 24) + "带(加带号)";
            return CoordinateSystem.createBeijing1954();
          } else if (srid > 2421 && srid < 2443)
          {
            strCoorDes = "北京54坐标系3度分带" + String.valueOf(srid - 2421 + 24) + "带(不加带号)";
            return CoordinateSystem.createBeijing1954();
          } else if (srid > 21412 && srid < 21424)
          {
            strCoorDes = "北京54坐标系6度分带" + String.valueOf(srid - 21412 + 12) + "带(加带号)";
            return CoordinateSystem.createBeijing1954();
          } else if (srid > 21452 && srid < 21464)
          {
            strCoorDes = "北京54坐标系6度分带" + String.valueOf(srid - 21452 + 12) + "带(不加带号)";
            return CoordinateSystem.createBeijing1954();
          } else if (srid > 2348 && srid < 2370)
          {
            strCoorDes = "西安80坐标系3度分带" + String.valueOf(srid - 2348 + 24) + "带(加带号)";
            return CoordinateSystem.createXian1980();
          } else if (srid > 2369 && srid < 2391)
          {
            strCoorDes = "西安80坐标系3度分带" + String.valueOf(srid - 2369 + 24) + "带(不加带号)";
            return CoordinateSystem.createXian1980();
          } else if (srid > 2326 && srid < 2338)
          {
            strCoorDes = "西安80坐标系6度分带" + String.valueOf(srid - 2326 + 12) + "带(加带号)";
            return CoordinateSystem.createXian1980();
          } else if (srid > 2337 && srid < 2349)
          {
            strCoorDes = "西安80坐标系6度分带" + String.valueOf(srid - 2337 + 12) + "带(不加带号)";
            return CoordinateSystem.createXian1980();
          } else if (srid > 4512 && srid < 4534)
          {
            strCoorDes = "国家2000坐标系3度分带" + String.valueOf(srid - 4512 + 24) + "带(加带号)";
            return CoordinateSystem.createCGCS2000();
          } else if (srid > 4533 && srid < 4555)
          {
            strCoorDes = "国家2000坐标系3度分带" + String.valueOf(srid - 4533 + 24) + "带(不加带号)";
            return CoordinateSystem.createCGCS2000();
          } else if (srid > 4490 && srid < 4502)
          {
            strCoorDes = "国家2000坐标系6度分带" + String.valueOf(srid - 4490 + 12) + "带(加带号)";
            return CoordinateSystem.createCGCS2000();
          } else if (srid > 4501 && srid < 4513)
          {
            strCoorDes = "国家2000坐标系6度分带" + String.valueOf(srid - 4501 + 12) + "带(不加带号)";
            return CoordinateSystem.createCGCS2000();
          } else if (srid > 1000022 && srid < 1000044)
          {
            strCoorDes = "WGS84高斯投影坐标系3度分带" + (srid - 1000022 + 24) + "带(加带号)";
            return CoordinateSystem.createWGS84();
          } else if (srid > 1000043 && srid < 1000065)
          {
            strCoorDes = "WGS84高斯投影坐标系3度分带" + (srid - 1000043 + 24) + "带(不加带号)";
            return CoordinateSystem.createWGS84();
          } else if (srid > 1000000 && srid < 1000012)
          {
            strCoorDes = "WGS84高斯投影坐标系6度分带" + (srid - 1000000 + 12) + "带(加带号)";
            return CoordinateSystem.createWGS84();
          } else if (srid > 1000011 && srid < 1000023)
          {
            strCoorDes = "WGS84高斯投影坐标系6度分带" + (srid - 1000011 + 12) + "带(不加带号)";
            return CoordinateSystem.createWGS84();
          } else if (srid == 1000000)
          {
            strCoorDes = "北京地方坐标系";
            return CoordinateSystem.createBeijing1954();
          } else
          {
            strCoorDes = "未知坐标系统";
          }
        // TODO liubo 2017年6月11日19:22:34  找不到坐标系，必须报异常
        return null;
      }

    public static String getCoordinateSystemName(int srid)
      {
        // TODO 这里必须要求算其真实地理坐标系统 这里只是为测试用 liubo 2016年8月8日15:11:21
        String strCoorDes = null;
        if (srid == 3395 || srid == 900913 || srid == 3857 || srid == 102100 || srid == 102113 || srid == 54004)
          {
            strCoorDes = "世界墨卡托投影坐标系";
          } else if (srid == 4326)
          {
            strCoorDes = "WGS84坐标系 经纬度";
          } else if (srid == 4214)
          {
            strCoorDes = "北京1954坐标系 经纬度";
          } else if (srid == 4610)
          {
            strCoorDes = "西安1980坐标系 经纬度";
          } else if (srid == 4490)
          {
            strCoorDes = "国家2000坐标系 经纬度";
          } else if (srid > 2400 && srid < 2422)
          {
            strCoorDes = "北京54坐标系3度分带" + String.valueOf(srid - 2400 + 24) + "带(加带号)";
          } else if (srid > 2421 && srid < 2443)
          {
            strCoorDes = "北京54坐标系3度分带" + String.valueOf(srid - 2421 + 24) + "带(不加带号)";
          } else if (srid > 21412 && srid < 21424)
          {
            strCoorDes = "北京54坐标系6度分带" + String.valueOf(srid - 21412 + 12) + "带(加带号)";
          } else if (srid > 21452 && srid < 21464)
          {
            strCoorDes = "北京54坐标系6度分带" + String.valueOf(srid - 21452 + 12) + "带(不加带号)";
          } else if (srid > 2348 && srid < 2370)
          {
            strCoorDes = "西安80坐标系3度分带" + String.valueOf(srid - 2348 + 24) + "带(加带号)";
          } else if (srid > 2369 && srid < 2391)
          {
            strCoorDes = "西安80坐标系3度分带" + String.valueOf(srid - 2369 + 24) + "带(不加带号)";
          } else if (srid > 2326 && srid < 2338)
          {
            strCoorDes = "西安80坐标系6度分带" + String.valueOf(srid - 2326 + 12) + "带(加带号)";
          } else if (srid > 2337 && srid < 2349)
          {
            strCoorDes = "西安80坐标系6度分带" + String.valueOf(srid - 2337 + 12) + "带(不加带号)";
          } else if (srid > 4512 && srid < 4534)
          {
            strCoorDes = "国家2000坐标系3度分带" + String.valueOf(srid - 4512 + 24) + "带(加带号)";
          } else if (srid > 4533 && srid < 4555)
          {
            strCoorDes = "国家2000坐标系3度分带" + String.valueOf(srid - 4533 + 24) + "带(不加带号)";
          } else if (srid > 4490 && srid < 4502)
          {
            strCoorDes = "国家2000坐标系6度分带" + String.valueOf(srid - 4490 + 12) + "带(加带号)";
          } else if (srid > 4501 && srid < 4513)
          {
            strCoorDes = "国家2000坐标系6度分带" + String.valueOf(srid - 4501 + 12) + "带(不加带号)";
          } else if (srid > 1000022 && srid < 1000044)
          {
            strCoorDes = "WGS84高斯投影坐标系3度分带" + (srid - 1000022 + 24) + "带(加带号)";
          } else if (srid > 1000043 && srid < 1000065)
          {
            strCoorDes = "WGS84高斯投影坐标系3度分带" + (srid - 1000043 + 24) + "带(不加带号)";
          } else if (srid > 1000000 && srid < 1000012)
          {
            strCoorDes = "WGS84高斯投影坐标系6度分带" + (srid - 1000000 + 12) + "带(加带号)";
          } else if (srid > 1000011 && srid < 1000023)
          {
            strCoorDes = "WGS84高斯投影坐标系6度分带" + (srid - 1000011 + 12) + "带(不加带号)";
          } else if (srid == 1000000)
          {
            strCoorDes = "北京地方坐标系";
          }
        // TODO liubo 2017年6月11日19:22:34  找不到坐标系，必须报异常
        return strCoorDes;
      }

  }
